package com.study.retrofitrealize;

import com.study.retrofitrealize.annotation.FIELD;
import com.study.retrofitrealize.annotation.GET;
import com.study.retrofitrealize.annotation.POST;
import com.study.retrofitrealize.annotation.QUERY;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Request;

/**
 * 作者： zjf 10/7/20 2:42 PM
 * 参考：
 * 描述：
 */
public class ClassMethod {


    private final Call.Factory callFactory;
    private final HttpUrl baseUrl;
    private FormBody.Builder formBodyBuilder;
    private final ParameterStore[] parameterStores;
    private final String httpMethod;
    private final String relativeURL;
    private HttpUrl.Builder httpUrlBuilder;

    /**
     * 构造方法
     */
    public ClassMethod(Builder builder) {
        //获取到okHttp实例
        this.callFactory = builder.retrofit.callFactory;
        //获取到设置的baseUrl
        this.baseUrl = builder.retrofit.baseUrl;
        //获取解析的方法参数的注解信息
        this.parameterStores = builder.parameterStores;
        //获取请求类型
        this.httpMethod = builder.httpMethod;
        //获取请求路径
        this.relativeURL = builder.relativeURL;
        //是否有请求体
        boolean hasBody = builder.hasBody;

        //如果有请求体,创建一个form表单请求
        if (hasBody) {
            formBodyBuilder = new FormBody.Builder();
        }
    }

    /**
     * 添加get请求的参数
     *
     * @param key   参数名
     * @param value 参数值
     */
    public void addQueryParameter(String key, String value) {
        if (httpUrlBuilder == null) {
            httpUrlBuilder = baseUrl.newBuilder(relativeURL);
        }

        assert httpUrlBuilder != null;
        httpUrlBuilder.addQueryParameter(key, value);
    }

    /**
     * 添加post请求的参数
     *
     * @param key   参数名
     * @param value 参数值
     */
    public void addFieldParameter(String key, String value) {
        formBodyBuilder.add(key, value);
    }

    /**
     * 建造者
     */
    public static class Builder {
        /**
         * 方法上的注解
         */
        private final Annotation[] methodAnnotations;
        /**
         * 获取方法参数上的注解
         */
        private final Annotation[][] parameterAnnotations;
        /**
         * MyRetrofit实例
         */
        private final MyRetrofit retrofit;
        /**
         * 请求方式(GET或POST)
         */
        private String httpMethod;
        /**
         * 获取注解的值,请求路径
         */
        private String relativeURL;
        /**
         * 是否有请求体
         */
        private boolean hasBody;
        /**
         * 保存方法参数上的注解和注解的参数的值
         */
        private ParameterStore[] parameterStores;

        public Builder(MyRetrofit retrofit, Method method) {
            this.retrofit = retrofit;
            methodAnnotations = method.getAnnotations();
            parameterAnnotations = method.getParameterAnnotations();
        }

        public ClassMethod build() {

            /*
             * 解析方法上的注解
             */
            for (Annotation annotation : methodAnnotations) {
                if (annotation instanceof POST) {
                    this.httpMethod = "POST";
                    this.relativeURL = ((POST) annotation).value();
                    this.hasBody = true;
                } else if (annotation instanceof GET) {
                    this.httpMethod = "GET";
                    this.relativeURL = ((GET) annotation).value();
                    this.hasBody = false;
                }
            }

            /*
             * 解析方法参数上的注解
             * 遍历二维数组
             */
            int length = parameterAnnotations.length;
            parameterStores = new ParameterStore[length];
            for (int i = 0; i < length; i++) {
                Annotation[] annotations = parameterAnnotations[i];
                for (Annotation annotation : annotations) {
                    if (annotation instanceof FIELD) {
                        String value = ((FIELD) annotation).value();
                        parameterStores[i] = new ParameterStore.FieldParameterStore(value);
                    } else if (annotation instanceof QUERY) {
                        String value = ((QUERY) annotation).value();
                        parameterStores[i] = new ParameterStore.QueryParameterStore(value);
                    }
                }
            }

            return new ClassMethod(this);
        }
    }

    /**
     * 真正执行网络请求的方法
     * 注意:获得的代理对象实例每次调用方法都会走到这里
     *
     * @param args 方法参数
     * @return 方法返回值
     */
    public Object invoke(Object[] args) {
        for (int i = 0; i < parameterStores.length; i++) {
            parameterStores[i].apply(this, args[i].toString());
        }
        //最终的请求url
        HttpUrl finalUrl;

        //方法参数没有注解的时候为空,直接拿到方法的注解进行拼接
        if (httpUrlBuilder == null) {
            httpUrlBuilder = baseUrl.newBuilder(relativeURL);
        }
        assert httpUrlBuilder != null;
        finalUrl = httpUrlBuilder.build();

        //请求体
        FormBody formBody = null;
        //不为空,说明有请求体
        if (formBodyBuilder != null) {
            formBody = formBodyBuilder.build();
        }

        //构建请求体
        Request request = new Request.Builder().url(finalUrl).method(httpMethod, formBody).build();
        return callFactory.newCall(request);
    }
}
